//IO相关
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageSeriesWriter.h"

/// 计算两点间的距离
static double distance(const double a[3], const double b[3]) {
    return sqrt((b[0]-a[0])*(b[0]-a[0]) + (b[1]-a[1])*(b[1]-a[1]) + (b[2]-a[2])*(b[2]-a[2]));
}

int main(int argc, char *argv[])
{

    typedef   float           InternalPixelType;
    const     unsigned int    Dimension = 3;//输入为三维
    typedef itk::Image< InternalPixelType, Dimension >  InternalImageType;

    typedef  float          OutputPixelType;
    const unsigned int      OutputDimension = 2;//输出为二维
    typedef itk::Image< OutputPixelType, OutputDimension > OutputImageType;

    typedef  itk::ImageSeriesReader< InternalImageType > ReaderType;
    typedef  itk::ImageSeriesWriter<  InternalImageType,OutputImageType  > WriterType;//自动在输入和输出之间转换

    ReaderType::Pointer reader = ReaderType::New();
    WriterType::Pointer writer = WriterType::New();

    //DICOM数据的ImageIO
    typedef itk::GDCMImageIO             ImageIOType;
    ImageIOType::Pointer gdcmIO = ImageIOType::New();

    //文件生成器
    typedef itk::GDCMSeriesFileNames     NamesGeneratorType;
    NamesGeneratorType::Pointer namesGenerator = NamesGeneratorType::New();
    namesGenerator->SetInputDirectory("/root/dicom/data/toolDicom");

    //保存文件名
    const ReaderType::FileNamesContainer & filenames =
            namesGenerator->GetInputFileNames();

    reader->SetImageIO(gdcmIO);
    reader->SetFileNames(filenames);

    try
    {
        reader->Update();
    }
    catch (itk::ExceptionObject &excp)
    {
        std::cerr << "Exception thrown while writing the image" << std::endl;
        std::cerr << excp << std::endl;
        system("pause");
        return EXIT_FAILURE;
    }

    //显示Image Space的不同方法
    std::cout << "Spacing = ";
    std::cout << gdcmIO->GetSpacing(0) <<" "<<gdcmIO->GetSpacing(1)<<" "<<gdcmIO->GetSpacing(2) << std::endl;

    //显示Image GetDimensions
    std::cout << "GetDimensions = ";
    std::cout << gdcmIO->GetDimensions(0) <<" "<<gdcmIO->GetDimensions(1)<<" "<<gdcmIO->GetDimensions(2) << std::endl;

    std::cout << "Origin = ";
    std::cout << gdcmIO->GetOrigin(0) << " " << gdcmIO->GetOrigin(1) << " " << gdcmIO->GetOrigin(2) << std::endl;
    const InternalImageType::SpacingType& inputSpacing = reader->GetOutput()->GetSpacing();
    std::cout << "Spacing=";
    std::cout << inputSpacing[0] << " " << inputSpacing[1] << " " << inputSpacing[2] << std::endl;


    float *pData = reader->GetOutput()->GetBufferPointer();
    //
    int dim[3] = { int(gdcmIO->GetDimensions(0)), int(gdcmIO->GetDimensions(1)), 558 };

    // y,z 方向相反，所以要
    double IronBallVector[6][3] = {
//        {(20 + 1)/inputSpacing[0], (140 - 50 + 1)/inputSpacing[1], (107.5 - 46)/inputSpacing[2]},
//        {(60 + 1)/inputSpacing[0], (140 - 50 + 1)/inputSpacing[1], (107.5 - 46)/inputSpacing[2]},
//        {(100 + 1)/inputSpacing[0], (140 - 50 + 1)/inputSpacing[1], (107.5 - 46)/inputSpacing[2]},
//        {(20 + 1)/inputSpacing[0], (140 - 130 + 1)/inputSpacing[1], (107.5 - 46)/inputSpacing[2]},
//        {(60 + 1)/inputSpacing[0], (140 - 130 + 1)/inputSpacing[1], (107.5 - 76)/inputSpacing[2]},
//        {(100 + 1)/inputSpacing[0], (140 - 130 + 1)/inputSpacing[1], (107.5 - 106)/inputSpacing[2]}

        {(17.5 + 2)/inputSpacing[0], (140 - 60 + 1.8)/inputSpacing[1], (107.6 - 29+ 1.8)/inputSpacing[2]},
        {(102.5 + 2)/inputSpacing[0], (140 - 60 + 1.8)/inputSpacing[1], (107.6 - 29+ 1.8)/inputSpacing[2]},
        {(17.5 + 2)/inputSpacing[0], (140 - 120 + 1.8)/inputSpacing[1], (107.6 - 29+ 1.8)/inputSpacing[2]},
        {(83.5 + 2)/inputSpacing[0], (140 - 120 + 1.8)/inputSpacing[1], (107.6 - 29+ 1.8)/inputSpacing[2]},
    };

    for(int iron = 0; iron < 4; iron++) {
        double x = IronBallVector[iron][0];
        double y = IronBallVector[iron][1];
        double z = IronBallVector[iron][2];

        for(int k = z - 20; k < z + 20; k++) {
            for(int j = y - 20; j < y + 20; j++) {
                for(int i = x - 20; i < x + 20; i++) {
                    double p0[3] = {i*1.0, j*1.0, k*1.0};
                    if(distance(p0, IronBallVector[iron]) <= 1.0 / inputSpacing[0]) {
                        pData[k * dim[0] * dim[1] + j * dim[0] + i] = 10000;
                    }
                }
            }
        }
    }


//    for(int k = 0; k < dim[2]; k++) {
//        for(int j = 0; j < dim[1]; j++) {
//            for(int i = 0; i < dim[0]; i++) {
//                double p0[3] = {i*1.0, j*1.0, k*1.0};
//                if(i < 100 && j < 200) {
//                    pData[k * dim[0] * dim[1] + j * dim[0] + i] = 0;
//                }
//            }
//        }
//    }


    //输出文件夹
    const char * outputDirectory = "/root/dicom/data/toolDicom22";
    itksys::SystemTools::MakeDirectory(outputDirectory);

    //设置输出文件夹
    namesGenerator->SetOutputDirectory(outputDirectory);

    writer->SetFileNames(namesGenerator->GetOutputFileNames());
    //用原来的文件头
    writer->SetMetaDataDictionaryArray(
                reader->GetMetaDataDictionaryArray());

    writer->SetInput(reader->GetOutput());
    writer->SetImageIO(gdcmIO);
    try
    {
        writer->Update();
    }
    catch (itk::ExceptionObject & excep)
    {
        std::cerr << "Exception caught !" << std::endl;
        std::cerr << excep << std::endl;
        system("pause");
        return EXIT_FAILURE;
    }

    system("pause");
    return EXIT_SUCCESS;
}
